/** \file spi_hw.cc
 *    This file contains (or, it might someday) a class to run a hardware SPI port on
 *    an AVR processor. For now, a software-run, bit-banging SPI port is being used,
 *    as it's easier to debug. Really. 
 */


//-------------------------------------------------------------------------------------
/** This method sets up the SPI port with parameters which work for communication with
 *  a nRF24L01 radio module. 
 */

void nRF24L01_text::spi_setup (void)
    {
    // Set data directions of MOSI and SCK pins to outputs
    SPI_IO_DDR |= SPI_MOSI_MASK | SPI_SCK_MASK;

    // Ensure that MISO (PB3) is an input
    SPI_IO_DDR &= ~SPI_MISO_MASK;

    // Set the SPI control register: Enable SPI, set as master, prescale osc. / 64
    SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0);
//     SPCR |= (1 << CPOL);
//     SPCR |= (1 << CPHA);
    ///////// Note: NL had CPOL set and a slower clock (SPR1 set)

    // Beginning state: SS is high, CE is low for low-power not-talking mode
    *port_SS |= mask_SS;
    *port_CE &= ~mask_CE;
    }


//-------------------------------------------------------------------------------------
/** This method sends a bunch of bytes through the SPI port to the radio and 
 *  simultaneously receives bytes from the radio. The data to be sent is in the given
 *  character array; when the transfer is complete, the array will contain data which
 *  was sent back by the radio. 
 *  @param data A pointer to an array of characters containing data to be sent
 *  @param num The number of bytes to be sent and received from and to the array
 *  @return True if the transfer was completed successfully, false if not
 */

bool nRF24L01_text::spi_exch_bytes (unsigned char* data, unsigned char num)
    {
    unsigned char byte_ctr;                 // Counts through the bytes being sent
    unsigned int tout_ctr;                  // For timeout waiting for transmitter

    for (byte_ctr = 0; byte_ctr < num; byte_ctr++)  ////////////////
        *p_serport << hex << data[byte_ctr] << " ";
    *p_serport << "--> ";

    // Drop the chip select (slave select) bit
    *port_SS &= ~mask_SS; 

    // Transmit each byte, then wait until the exchange has been completed
    for (byte_ctr = 0; byte_ctr < num; byte_ctr++)
        {
        SPDR = data[byte_ctr];              // Put data in SPI data register

        // Wait for transmission to be completed; if we time out, exit
        for (tout_ctr = 0; (SPSR & (1 << SPIF)) == 0; tout_ctr++)
            if (tout_ctr > nRF24_SPI_TIMEOUT) return (false);

        // The data has arrived, so save it and increment to the next byte
        data[byte_ctr] = SPDR;
//         data++;
        }

    // Raise the Slave Select bit again
    *port_SS |= mask_SS;

    for (byte_ctr = 0; byte_ctr < num; byte_ctr++)  ////////////////
        *p_serport << data[byte_ctr] << " ";
    *p_serport << endl;
    }
